//Copyright (c) Microsoft Corporation.  All rights reserved.

using System;
using System.Collections.Generic;
using System.Text;

namespace Eas.WebCrawler.Common.Threading {
    /// <summary>Will track and report IAsyncResults that were opened through calls to 'Begin' but not closed through an 'End'.</summary>
    /// <remarks>This class only works when DEBUG is defined, otherwise the functions do nothing (and are conditionally compiled out).</remarks>
    public class AsyncResultTracker {
#if DEBUG
        Dictionary<IAsyncResult, string> _OpenResults = new Dictionary<IAsyncResult, string>();
#endif

        /// <summary>Clears any open results.</summary>
        [System.Diagnostics.Conditional("DEBUG")]
        public void Clear() {
#if DEBUG
            _OpenResults.Clear();
#endif
        }

        /// <summary>Logs that an <see cref="IAsyncResult"/> was opened through the 'Begin' half of an asynchronous method.</summary>
        /// <param name="result">The result returned from the 'Begin' method.</param>
        /// <param name="textHint">A text hint that will be displayed if this result is not closed (for debugging).</param>
        [System.Diagnostics.Conditional("DEBUG")]
        public void OpenResult(IAsyncResult result, string textHint) {
#if DEBUG
            lock (_OpenResults) {
                //System.Diagnostics.Trace.WriteLine(string.Format("Result opened for action {0} with Result={1}", textHint, result.GetHashCode()));
                if (_OpenResults.ContainsKey(result)) {
                    System.Diagnostics.Trace.WriteLine(string.Format(System.Globalization.CultureInfo.InvariantCulture, "Current Result already opened.  Action is {0}", textHint));
                    System.Diagnostics.Debug.Fail("Current result already opened");
                }
                _OpenResults.Add(result, textHint);
            }
#endif
        }

        /// <summary>Closes an opened result.</summary>
        /// <param name="result">The <see cref="IAsyncResult"/> that was opneed.</param>
        [System.Diagnostics.Conditional("DEBUG")]
        public void CloseResult(IAsyncResult result) {
#if DEBUG
            lock (_OpenResults) {
                if (!_OpenResults.ContainsKey(result)) {
                    System.Diagnostics.Trace.WriteLine(string.Format(System.Globalization.CultureInfo.InvariantCulture, "Trying to close unopened result {0}.", result.GetHashCode()));
                    System.Diagnostics.Debug.Fail("Closing unopened result.");
                }
                _OpenResults.Remove(result);
            }
#endif
        }

        /// <summary>Checks for any open (unclosed) resutls and reports on them.</summary>
        [System.Diagnostics.Conditional("DEBUG")]
        public void ValidateNoResultsAreOpened() {
#if DEBUG
            lock (_OpenResults) {
                if (_OpenResults.Count > 0) {
                    foreach (KeyValuePair<IAsyncResult, string> result in _OpenResults) {
                        System.Diagnostics.Trace.WriteLine(string.Format(System.Globalization.CultureInfo.InvariantCulture, "Invalid open result {0} with action {1} found", result.Key.GetHashCode(), result.Value));
                    }
                    System.Diagnostics.Trace.WriteLine( "Invalid open results found.");
                    System.Diagnostics.Debug.Fail("Invalid open results found");
                }
            }
#endif
        }

    }
}
